package com.xiaoshuidi.cloud.module.member.service.activities;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.common.util.json.JsonUtils;
import com.xiaoshuidi.cloud.framework.security.core.util.SecurityFrameworkUtils;
import com.xiaoshuidi.cloud.module.member.controller.admin.activities.vo.ActivitiesPointVO;
import com.xiaoshuidi.cloud.module.member.controller.admin.activities.vo.ActivitiesStatisticsVO;
import com.xiaoshuidi.cloud.module.member.controller.admin.activities.vo.EnrollItemVO;
import com.xiaoshuidi.cloud.module.member.controller.app.activities.vo.EnrollItem;
import com.xiaoshuidi.cloud.module.member.controller.app.activities.vo.EnrollListVO;
import com.xiaoshuidi.cloud.module.member.controller.app.activities.vo.EnrollStatusPageVO;
import com.xiaoshuidi.cloud.module.member.controller.app.activities.vo.EnrollVO;
import com.xiaoshuidi.cloud.module.member.enums.ActivitiesEnrollStaticsEnum;
import com.xiaoshuidi.cloud.module.member.enums.WriteOffStatusEnum;
import com.xiaoshuidi.cloud.module.member.enums.point.PointRecordEnums;
import com.xiaoshuidi.cloud.module.member.mapper.activities.MemberActivitiesEnrollMapper;
import com.xiaoshuidi.cloud.module.member.mq.message.VerifyCodeMessage;
import com.xiaoshuidi.cloud.module.member.pojo.activities.MemberActivities;
import com.xiaoshuidi.cloud.module.member.pojo.activities.MemberActivitiesEnroll;
import com.xiaoshuidi.cloud.module.member.repository.MemberActivitiesEnrollRepository;
import com.xiaoshuidi.cloud.module.member.repository.MemberActivitiesRepository;
import com.xiaoshuidi.cloud.module.member.service.point.MemberPointsService;
import com.xiaoshuidi.cloud.module.member.util.QrCodeGeneratorUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTimeUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import static cn.hutool.core.date.DatePattern.NORM_DATETIME_PATTERN;

@Slf4j
@Service
@RequiredArgsConstructor
public class MemberActivitiesEnrollServiceImpl extends ServiceImpl<MemberActivitiesEnrollMapper, MemberActivitiesEnroll> implements MemberActivitiesEnrollService {
    private final MemberActivitiesEnrollRepository memberActivitiesEnrollRepository;

    private final MemberActivitiesRepository memberActivitiesRepository;

    private final MemberPointsService memberPointsService;

    @Override
    public Boolean enroll(EnrollVO vo) {
        memberActivitiesEnrollRepository.enroll(vo);
        return true;
    }

    @Override
    public Boolean enrollOrNot(Long activityId) {
        //是否在报名时间
        if (memberActivitiesRepository.enrollOrNot(activityId)) {
            //在报名时间,看是否已报过名了
            if (memberActivitiesEnrollRepository.enrollOrNot(activityId)) {
                //未报名，可以报名
                return true;
            }
            //已报名，不可以报名
            return false;
        }
        //不在报名时间不能报名
        return false;
    }

    @Override
    public PageResult<EnrollListVO> getStatusPage(EnrollStatusPageVO page) {
        IPage<EnrollListVO> result = memberActivitiesRepository.getStatusPage(page);
        PageResult<EnrollListVO> pageResult = PageResult.empty();
        List<EnrollListVO> records = result.getRecords();
        records = records.stream().peek(c -> {
            //设置图片二维码
            String codeStr = QrCodeGeneratorUtil.generateQrCode(c.getVerifyCode(), 300, 300);
            c.setImageCodeStr(codeStr);
        }).collect(Collectors.toList());
        pageResult.setList(records);
        pageResult.setTotal(result.getTotal());
        if (page.getStatus().intValue() == WriteOffStatusEnum.EXPIRED.getCode().intValue()) {
            //更新记录状态为已失效
            List<Long> collect = result.getRecords().stream().map(EnrollListVO::getId).collect(Collectors.toList());
            if (collect != null && collect.size() > 0) {
                memberActivitiesEnrollRepository.updateStatus(collect);
            }
        }
        return pageResult;
    }

    @Override
    public PageResult<EnrollListVO> getPage(EnrollStatusPageVO page) {
        IPage<EnrollListVO> result = memberActivitiesRepository.getPage(page);
        //处理已过期的二维码
        List<EnrollListVO> orignRecords = result.getRecords();
        List<EnrollListVO> records = orignRecords;
        List<EnrollListVO> collect = orignRecords.stream().filter(e -> LocalDateTime.now().isAfter(e.getEndTime())).collect(Collectors.toList());
        //其他两种状态的list,待核销和已核销状态的集合
        records.removeAll(collect);
        //这些二维码都需要批量改成过期
        List<EnrollListVO> needUpdateStatus = collect.stream().filter(c -> c.getStatus().intValue() != WriteOffStatusEnum.EXPIRED.getCode().intValue()).collect(Collectors.toList());
        if (needUpdateStatus != null && needUpdateStatus.size() > 0) {
            memberActivitiesEnrollRepository.updateStatus(needUpdateStatus.stream().map(EnrollListVO::getId).collect(Collectors.toList()));
        }

        //拼装list
        collect = collect.stream().peek(e -> e.setStatus(WriteOffStatusEnum.EXPIRED.getCode())).collect(Collectors.toList());
        records.addAll(collect);
        PageResult<EnrollListVO> pageResult = PageResult.empty();
        //处理活动项
        records.stream().peek(e -> {
            if (StringUtils.isNotEmpty(e.getFillItemDetail())) {
                e.setItems(JsonUtils.parseArray(e.getFillItemDetail(), EnrollItem.class));
            }
        }).collect(Collectors.toList());
        Collections.sort(records, new Comparator<EnrollListVO>() {
            @Override
            public int compare(EnrollListVO o1, EnrollListVO o2) {
                return o2.getEnrollTime().compareTo(o1.getEnrollTime());
            }
        });
        pageResult.setTotal(result.getTotal());
        pageResult.setList(records);

        return pageResult;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean writeOff(Long id, EnrollItemVO enrollItemVO) {
        //检验是否过期,查询活动结束时间
        EnrollListVO enrollListVO = memberActivitiesEnrollRepository.validateExpired(id);

        //判断是否过期
        if (LocalDateTime.now().isAfter(enrollListVO.getEndTime())) {
            //更改状态
            if (enrollListVO.getStatus().intValue() != WriteOffStatusEnum.EXPIRED.getCode().intValue()) {
                memberActivitiesEnrollRepository.updateStatus(Arrays.asList(id));
            }
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "核销码已过期!");
        }

        //判断核销码是否正确
        Boolean flag = memberActivitiesEnrollRepository.validateCode(id, enrollItemVO.getVerifyCode());
        if (!flag) {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "核销码不正确!");
        }
        memberActivitiesEnrollRepository.writeOff(id, enrollItemVO.getVerifiedBy());
        //发送积分
        //查找积分赠送的租户，以及参加活动赠送积分
        ActivitiesPointVO pointVO = memberActivitiesEnrollRepository.getActivitiesPoint(id);
        if (pointVO != null && pointVO.getBonusPoints() != null) {
            //发送积分
            try {
                memberPointsService.memberPointsChange(pointVO.getUserId(), pointVO.getBonusPoints(), PointRecordEnums.ACTIVITIES, "活动报名奖励积分");
            } catch (Exception e) {
                log.error("用户活动报名奖励积分异常", e.getMessage());
            }
        }
        return true;
    }

    @Override
    public List<ActivitiesStatisticsVO> statistics(Long activityId) {
        //查询活动信息
        MemberActivities memberActivities = memberActivitiesRepository.getById(activityId);
        final LocalDateTime endTime = memberActivities.getEndTime();
        List<MemberActivitiesEnroll> list = memberActivitiesEnrollRepository.getAllEnrollInfo(activityId);
        List<ActivitiesStatisticsVO> result = new ArrayList<>();
        if (list != null && list.size() > 0) {
            for (ActivitiesEnrollStaticsEnum value : ActivitiesEnrollStaticsEnum.values()) {
                ActivitiesStatisticsVO vo = new ActivitiesStatisticsVO();
                vo.setCode(value.getCode());
                vo.setName(value.getName());
                if (vo.getCode().equals(ActivitiesEnrollStaticsEnum.ENROLLMENT.getCode())) {
                    vo.setValue(list.size() + "/" + memberActivities.getNum());
                } else if (vo.getCode().equals(ActivitiesEnrollStaticsEnum.VERIFIED.getCode())) {
                    long count = list.stream().filter(a -> a.getStatus().intValue() == WriteOffStatusEnum.WRITTEN_OFF.getCode().intValue())
                            .count();
                    vo.setValue(Long.toString(count));
                } else if (vo.getCode().equals(ActivitiesEnrollStaticsEnum.TO_BE_VERIFIED.getCode())) {
                    long count = list.stream().filter(a ->
                            (a.getStatus().intValue() == WriteOffStatusEnum.TO_BE_WRITTEN_OFF.getCode().intValue())
                                    && (LocalDateTime.now().isBefore(endTime) || LocalDateTime.now() == endTime)
                    ).count();
                    vo.setValue(Long.toString(count));
                }
                result.add(vo);
            }
        } else {
            for (ActivitiesEnrollStaticsEnum value : ActivitiesEnrollStaticsEnum.values()) {
                ActivitiesStatisticsVO vo = new ActivitiesStatisticsVO();
                vo.setCode(value.getCode());
                vo.setName(value.getName());
                if (vo.getCode().equals(ActivitiesEnrollStaticsEnum.ENROLLMENT.getCode())) {
                    vo.setValue("0/" + memberActivities.getNum());
                } else {
                    vo.setValue("0");
                }
                result.add(vo);
            }
        }
        return result;
    }

    @Override
    public void doVerifyCodeMessage(VerifyCodeMessage verifyCodeMessage) {
        LocalDateTime now = LocalDateTime.now();
        if (verifyCodeMessage.getEndTime() != null && (verifyCodeMessage.getEndTime().isBefore(now) || verifyCodeMessage.getEndTime() == now)) {
            //更改状态 为已失效
            memberActivitiesEnrollRepository.updateStatus(Arrays.asList(verifyCodeMessage.getId()));
        }
    }

    @Override
    public List<EnrollListVO> exportEnrollList(EnrollStatusPageVO form) {
        List<EnrollListVO> list = memberActivitiesEnrollRepository.getEnrollList(form);
        //处理已过期的二维码
        List<EnrollListVO> records = list;
        List<EnrollListVO> collect = list.stream().filter(e -> LocalDateTime.now().isAfter(e.getEndTime())).collect(Collectors.toList());
        //其他两种状态的list,待核销和已核销状态的集合
        records.removeAll(collect);
        //这些二维码都需要批量改成过期
        List<EnrollListVO> needUpdateStatus = collect.stream().filter(c -> c.getStatus().intValue() != WriteOffStatusEnum.EXPIRED.getCode().intValue()).collect(Collectors.toList());
        if (needUpdateStatus != null && needUpdateStatus.size() > 0) {
            memberActivitiesEnrollRepository.updateStatus(needUpdateStatus.stream().map(EnrollListVO::getId).collect(Collectors.toList()));
        }

        //拼装list
        collect = collect.stream().peek(e -> e.setStatus(WriteOffStatusEnum.EXPIRED.getCode())).collect(Collectors.toList());
        records.addAll(collect);
        PageResult<EnrollListVO> pageResult = PageResult.empty();
        //处理活动项
        records.stream().peek(e -> {
            if (StringUtils.isNotEmpty(e.getFillItemDetail())) {
                e.setItems(JsonUtils.parseArray(e.getFillItemDetail(), EnrollItem.class));
                for (int i = 1; i <= e.getItems().size(); i++) {
                    EnrollItem item = e.getItems().get(i-1);
                    if (i==1){
                        e.setFill1(item.getKey()+":"+item.getValue());
                    }else if (i==2){
                        e.setFill2(item.getKey()+":"+item.getValue());
                    }else if (i==3){
                        e.setFill3(item.getKey()+":"+item.getValue());
                    }else if (i==4){
                        e.setFill4(item.getKey()+":"+item.getValue());
                    }else if (i==5){
                        e.setFill5(item.getKey()+":"+item.getValue());
                    }else if (i==6){
                        e.setFill6(item.getKey()+":"+item.getValue());
                    }else if (i==7){
                        e.setFill7(item.getKey()+":"+item.getValue());
                    }else if (i==8){
                        e.setFill8(item.getKey()+":"+item.getValue());
                    }

                }
            }
            e.setEnrollTimeStr(LocalDateTimeUtil.format(e.getEnrollTime(), NORM_DATETIME_PATTERN));
            e.setVerifiedTimeStr(LocalDateTimeUtil.format(e.getVerifiedTime(), NORM_DATETIME_PATTERN));
            e.setStatusName(WriteOffStatusEnum.getNameByCode(e.getStatus()));
        }).collect(Collectors.toList());
        Collections.sort(records, new Comparator<EnrollListVO>() {
            @Override
            public int compare(EnrollListVO o1, EnrollListVO o2) {
                return o2.getEnrollTime().compareTo(o1.getEnrollTime());
            }
        });
        return records;
    }

    @Override
    public void updateUserId(Long oldUserId, Long userId) {
        memberActivitiesEnrollRepository.updateUserId(oldUserId,userId);
    }
}
